﻿using System;
using System.Collections.Generic;

namespace Patterns.Decorator {

    public static class AppliedExample {

        public static void Run() {
            // Create book
            Book book = new Book("Worley", "Inside ASP.NET", 10);
            book.Display();

            // Create video
            Video video = new Video("Spielberg", "Jaws", 23, 92);
            video.Display();

            // Make video borrowable, then borrow and display
            Console.WriteLine("\nMaking video borrowable:");

            Borrowable borrowvideo = new Borrowable(video);
            borrowvideo.BorrowItem("Customer #1");
            borrowvideo.BorrowItem("Customer #2");

            borrowvideo.Display();
        }
    }

    // "Component"
    abstract class LibraryItem {
        // Property
        public int NumCopies { get; set; }

        public abstract void Display();
    }

    // "ConcreteComponent"
    class Book : LibraryItem {
        private string Author { get; set; }
        private string Title { get; set; }

        // Constructor
        public Book(string author, string title, int numCopies) {
            Author = author;
            Title = title;
            NumCopies = numCopies;
        }

        public override void Display() {
            Console.WriteLine("\nBook ------ ");
            Console.WriteLine(" Author: {0}", Author);
            Console.WriteLine(" Title: {0}", Title);
            Console.WriteLine(" # Copies: {0}", NumCopies);
        }
    }

    // "ConcreteComponent"
    class Video : LibraryItem {
        private string Director { get; set; }
        private string Title { get; set; }
        private int PlayTime { get; set; }

        // Constructor
        public Video(string director, string title,
          int numCopies, int playTime) {
            Director = director;
            Title = title;
            NumCopies = numCopies;
            PlayTime = playTime;
        }

        public override void Display() {
            Console.WriteLine("\nVideo ----- ");
            Console.WriteLine(" Director: {0}", Director);
            Console.WriteLine(" Title: {0}", Title);
            Console.WriteLine(" # Copies: {0}", NumCopies);
            Console.WriteLine(" Playtime: {0}\n", PlayTime);
        }
    }

    // "Decorator"
    abstract class LibraryItemDecorator : LibraryItem {
        protected LibraryItem libraryItem;

        // Constructor
        public LibraryItemDecorator(LibraryItem libraryItem) {
            this.libraryItem = libraryItem;
        }

        public override void Display() {
            libraryItem.Display();
        }
    }

    // "ConcreteDecorator"
    class Borrowable : LibraryItemDecorator {
        protected List<string> borrowers = new List<string>();

        // Constructor
        public Borrowable(LibraryItem libraryItem)
            : base(libraryItem) { }

        public void BorrowItem(string name) {
            borrowers.Add(name);
            libraryItem.NumCopies--;
        }

        public void ReturnItem(string name) {
            borrowers.Remove(name);
            libraryItem.NumCopies++;
        }

        public override void Display() {
            base.Display();

            borrowers.ForEach(borrower =>
                Console.WriteLine(" borrower: " + borrower));
        }
    }
}
